---
title: Calling procedures
description: Learn how to call queries and mutations in your app.
---

## Overview

There are two ways to call procedures. In client components we use the
`useQuery`, 'useSuspenseQuery' and `useMutation` hooks to call the procedures.
On the server we use the `trpc` api caller to call the procedures directly.

## Client

The client uses [Tanstack Query](https://tanstack.com/query/latest) to manage
data fetching and caching.

### useQuery

```tsx
'use client'

import { useQuery } from '@tanstack/react-query'

import { useTRPC } from '#lib/trpc/react'

export function ContactPage(props: {
  params: {
    id: string
  }
}) {
  const trpc = useTRPC()

  const { data, isLoading } = useQuery(
    trpc.contacts.byId.queryOptions({
      id: props.params.id,
    }),
  )

  // render the page
}
```

### useSuspenseQuery

`useSuspenseQuery` is very useful as it guarantees data to be defined, so you
don't have to check for `isLoading` for conditional rendering. It also enables
you use Next.js streaming to render the page as soon as the data is available.

```tsx
// in a server component, eg page or layout
import { Suspense } from 'react'

import { ContactPage } from '#components/contact-page'
import { HydrateClient, prefetch, trpc } from '#lib/trpc/rsc'

export default async function Page(params: { id: string }) {
  prefetch(
    trpc.contacts.byId.queryOptions({
      id: params.id,
    }),
  )

  return (
    <HydrateClient>
      <Suspense fallback={<div>Loading...</div>}>
        <ContactPage id={params.id} />
      </Suspense>
    </HydrateClient>
  )
}
```

```tsx
// in a client component
import { useTRPC } from '#lib/trpc/react'

export function ContactPage(props: { id: string }) {
  const trpc = useTRPC()

  const { data } = useSuspenseQuery(
    trpc.contacts.byId.queryOptions({
      id,
    }),
  )

  return <div>{data.name}</div>
}
```

### useMutation

```tsx
'use client'

import { useAuth } from '@saas-ui/auth-provider'
import { useMutation, useQueryClient } from '@tanstack/react-query'

import { useTRPC } from '#lib/trpc/react'

export default function ProfilePage() {
  const { user } = useAuth()

  const trpc = useTRPC()

  const queryClient = useQueryClient()

  const mutation = useMutation(
    trpc.users.updateProfile.mutationOptions({
      onSettled: () => {
        // Invalidate the user cache, so the updated user is refetched
        queryClient.invalidateQueries({
          queryKey: trpc.users.updateProfile.queryKey(),
        })
      },
    }),
  )

  return (
    <button
      onClick={() => {
        mutation.mutate({
          name: 'John Doe',
        })
      }}
    >
      Save
    </button>
  )
}
```

## Server

To fetch and use the data on the server, you can use the `caller` object.

```ts
// app/[slug]/layout.tsx
import { caller } from '#lib/trpc/rsc'

export default Layout(props: {
  children: React.ReactNode
  params: {
    slug: string
  }
}) {
  const workspace = await caller.workspaces.bySlug({
    slug: props.params.slug,
  })

  if (!workspace) {
    notFound()
  }

  return (
    <div>
      {props.children}
    </div>
  )
}
```
